package mx.itesm.niveles;

import java.util.LinkedList;

import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.Entity;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.IEntityModifier.IEntityModifierListener;
import org.andengine.entity.modifier.JumpModifier;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.background.AutoParallaxBackground;
import org.andengine.entity.scene.background.ParallaxBackground.ParallaxEntity;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.ButtonSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.font.FontFactory;
import org.andengine.util.modifier.IModifier;

import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Typeface;
import mx.itesm.constants.ConstantesEscenas;
import mx.itesm.escenas.EscenaElegirPersonaje;
import mx.itesm.escenas.TipoEscena;
import mx.itesm.manejadores.ManejadorEscenas;


public class Nivel1 extends NivelBase {

	private Sprite fondoCielo;
	private Sprite fondoMontanas;
	private Sprite fondoCasas;
	
	private AnimatedSprite personaje;
	private AnimatedSprite minion;
	
	private Sprite piedra;
	private Sprite bala;
	private Sprite btnPausa;
	
	private LinkedList<Sprite> listaBalas;
	private LinkedList<AnimatedSprite> listaMinions;
	
	private static final int ANCHO_PANTALLA = ConstantesEscenas.ANCHO_PANTALLA;
	private static final int ALTO_PANTALLA = ConstantesEscenas.ALTO_PANTALLA;
	
	public static boolean locked = false;
	private boolean pausado = false;
	private boolean saltarPersonaje = false;
	private JumpModifier saltar;
	private float tiempo;
	private EstadoJuego estadoJuego;
	private Entity pantallaPausa;
	private Text txtPausa;
	
	private static final String PROGRESS = "Progress";
	private static final String LV1_SCORE = "Lv1_Score";
	
	private int suma = 5;
	
	private int leerScoreAnterior(String key) {
		SharedPreferences prefs = gActivity.getSharedPreferences(PROGRESS, 0);
		int prevScore = prefs.getInt(key, 0);
		return prevScore;
	}
	
	@Override
	public void crearEscena() {
		crearFondo();
		agregarObjetos();
		agregarBotonPausa();
		agregarControles();
		mostrarMarcador();
		animarElementos();
	}

	@Override
	public TipoEscena getTipoEscena() {
		return TipoEscena.ESCENA_LV1;
	}

	@Override
	public void crearFondo() {
		
		final AutoParallaxBackground autoParallaxBackground = new AutoParallaxBackground(0.1f, 0.1f, 0.5f, 10);
		setBackground(autoParallaxBackground);

		// El fondo mas lejano
		fondoCielo = new Sprite(0, 0, manejadorRecursos.cieloLv1TextureRegion, mVerticesObjetos);
		fondoCielo.setOffsetCenter(0, 0);
		// No se mueve 0.0f
		autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(0.0f, fondoCielo));
		
		// El fondo medio
		fondoMontanas = new Sprite(400, 280, manejadorRecursos.montanasLv1TextureRegion, mVerticesObjetos);
		fondoCielo.setOffsetCenter(0, 0);
		// Se mueve a la izquierda con un factor de 10
		autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-10.0f, fondoMontanas));
		
		// El fondo mas cercano
		fondoCasas = new Sprite(400, 170, manejadorRecursos.casasLv1TextureRegion, mVerticesObjetos);
		fondoCielo.setOffsetCenter(0, 0);
		
		// Se mueve a la izquierda con un factor de 15
		autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-15.0f, fondoCasas));
	}

	@Override
	public void agregarObjetos() {

		listaMinions = new LinkedList<AnimatedSprite>();
		listaBalas = new LinkedList<Sprite>();
		
		if (EscenaElegirPersonaje.getPersonajeElegido() == 1) {
			long[] duracionFrame = {250, 250, 250, 250};
			personaje = new AnimatedSprite(150, 100, manejadorRecursos.akaneJuegoRegion, mVerticesObjetos);
			personaje.animate(duracionFrame, 1, 4, true);
			personaje.setScale(0.6f);
			attachChild(personaje);
		}
		
		if (EscenaElegirPersonaje.getPersonajeElegido() == 2) {
			long[] duracionFrame = {200, 200, 200, 200};
			personaje = new AnimatedSprite(150, 100, manejadorRecursos.kazukiJuegoRegion, mVerticesObjetos);
			personaje.animate(duracionFrame, 1, 4, true);
			personaje.setScale(0.6f);
			attachChild(personaje);
		}
		
		piedra = new Sprite(750, 22, manejadorRecursos.piedraLv1Region, mVerticesObjetos);
		piedra.setScale(0.4f); // 0.7f
		attachChild(piedra);
	}
	
	@Override
	public void agregarControles() {
				
		setTouchAreaBindingOnActionDownEnabled(true);
		
		final Sprite btonDisparar = new Sprite(761, 40, manejadorRecursos.botonDispararRegion, mVerticesObjetos) {

			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {

				if (pSceneTouchEvent.isActionDown()) {
					if (!pausado)
						disparar();
				}
				return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX,
						pTouchAreaLocalY);
			}
		};
		
		final Sprite btonSaltar = new Sprite(40, 40, manejadorRecursos.botonSaltarRegion, mVerticesObjetos) {

			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {

				if (pSceneTouchEvent.isActionDown()) {

					if (!pausado) {
						
						if (suma == 5){
							if(saltarPersonaje == false){
								saltar = new JumpModifier(0.8f, 150, 150, 100, 100, -200);
							}

							IEntityModifierListener listener = new IEntityModifierListener() {
								@Override
								public void onModifierStarted(
										IModifier<IEntity> pModifier, IEntity pItem) {
									suma-=1;
									saltarPersonaje = true;
								}

								@Override
								public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
									suma = 5;
									saltarPersonaje = false;
								}
							};
							saltar.addModifierListener(listener);
							personaje.registerEntityModifier(saltar);
						}	
					}
				}
				return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX,
						pTouchAreaLocalY);
			}
		};
		
		registerTouchArea(btonDisparar);
		attachChild(btonDisparar);

		registerTouchArea(btonSaltar);
		attachChild(btonSaltar);
	}

	public void disparar() {
		bala = new Sprite(personaje.getX(), personaje.getY(), manejadorRecursos.balaRegion, mVerticesObjetos);
		listaBalas.add(bala);
		attachChild(bala);
	}
	
	@Override
	public void mostrarMarcador() {
		estadoJuego = new EstadoJuego(0, engine);
		camara.setHUD(estadoJuego);
	}

	@Override
	public void animarElementos() {
		
		piedra.registerUpdateHandler(new IUpdateHandler() {

			@Override
			public void reset() {}

			@Override
			public void onUpdate(float pSecondsElapsed) {
				
				if (pausado) {
					return;
				}
				
				float piedraX = piedra.getX() - 6;
				
				if (piedraX < 0)
					piedraX = ANCHO_PANTALLA;
				piedra.setPosition(piedraX, piedra.getY());
				
				if (personaje.collidesWith(piedra)) {
					estadoJuego.setVisible(false);
					ManejadorEscenas.getInstance().cargarEscenaPerdiste();
					ManejadorEscenas.getInstance().setEscena(
							TipoEscena.ESCENA_PERDISTE);
					ManejadorEscenas.getInstance().descargarEscenaNivel1();
				}
			}
		});	
		
		registerUpdateHandler(new IUpdateHandler() {

			@Override
			public void reset() {}
			
			@Override
			public void onUpdate(float pSecondsElapsed) {
				if (pausado) {
					return;
				}

				tiempo += pSecondsElapsed;

				if (tiempo >= 3.0f) {
					
					tiempo = 0;
					float px = (float)(Math.random()*(712 - 300 + 1) + 300);
					
					long[] duracionFrame = {200, 200};
					minion = new AnimatedSprite(px, 65, manejadorRecursos.minionJuegoRegion, mVerticesObjetos);
					minion.animate(duracionFrame, 1, 2, true);
					minion.setScale(0.8f);
					attachChild(minion);
					listaMinions.add(minion);
				}

				// PROBAR CHOQUES
				for (int i = listaBalas.size() - 1; i >= 0; i--) {
					Sprite bala = listaBalas.get(i);
					
					for (int k = listaMinions.size() - 1; k >= 0; k--) {
						
						AnimatedSprite e = listaMinions.get(k);
						if (bala.collidesWith(e)) {
							listaMinions.remove(k);
							listaBalas.remove(i);
							detachChild(e);
							detachChild(bala);
							estadoJuego.aumentarMarcador(200);
							
							if (estadoJuego.marcador >= 1000){
								estadoJuego.txtMarcador.setVisible(false);
								ManejadorEscenas.getInstance().cargarEscenaGanaste();
								ManejadorEscenas.getInstance().setEscena(TipoEscena.ESCENA_GANASTE);
								ManejadorEscenas.getInstance().descargarEscenaNivel1();
								Nivel2.locked = false;
							}
						}
					}
				}
				
				// Mover las balas y verificar si salen de la pantalla.
				for (int k = listaBalas.size() - 1; k >= 0; k--) {
					Sprite bala = listaBalas.get(k);
					bala.setX(bala.getX() + 10); // + 6
				}
			}
		});
	}

	@Override
	public void onBackKeyPressed() {
		
		if (!pausado) {	
			
			camara.setHUD(null);
			
			ManejadorEscenas.getInstance().cargarEscenaLoading();
			ManejadorEscenas.getInstance().setEscena(TipoEscena.ESCENA_CARGAR);
			ManejadorEscenas.getInstance().descargarEscenaNivel1();
			engine.registerUpdateHandler(new TimerHandler(0.2f, new ITimerCallback() {
				@Override
				public void onTimePassed(final TimerHandler pTimerHandler) {
					engine.unregisterUpdateHandler(pTimerHandler);
					ManejadorEscenas.getInstance().cargarEscenaMenu();
					ManejadorEscenas.getInstance().setEscena(TipoEscena.ESCENA_MENU);
				}
			}));			
			
		} else {
			reanudarJuego();
		}
	}

	@Override
	public void reanudarJuego() {
		camara.setHUD(estadoJuego);
		pausado = false;
		btnPausa.setVisible(true);
		Nivel1.this.detachChild(pantallaPausa);
	}
	
	@Override
	public void removerEscena() {
		this.detachSelf();
		this.dispose();
		guardarScore(estadoJuego.getMarcador());
	}
	
	private Entity crearPantallaPausa() {
		Rectangle rectPausa = new Rectangle(ANCHO_PANTALLA / 2,	ALTO_PANTALLA / 2, ANCHO_PANTALLA,
				ALTO_PANTALLA, mVerticesObjetos);
		rectPausa.setColor(0, 0, 0, 0.5f);
		
		Font tipoLetra = FontFactory.create(engine.getFontManager(),
				engine.getTextureManager(), 256, 256,
				Typeface.create(Typeface.DEFAULT, Typeface.BOLD_ITALIC), 40f, true, Color.BLACK);
		tipoLetra.load();
		tipoLetra.prepareLetters("Presbaktocinu ".toCharArray());

		txtPausa = new Text(400, 240, tipoLetra, "Press back to continue", 25, mVerticesObjetos);
		
		rectPausa.attachChild(txtPausa);
		
		return rectPausa;
	}
	
	private void agregarBotonPausa() {
		
		this.setTouchAreaBindingOnActionDownEnabled(true);

		btnPausa = new ButtonSprite(50, 420, manejadorRecursos.botonPausa1Region, mVerticesObjetos) {
			
			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {
				if (pSceneTouchEvent.isActionDown()) {
					pausado = true;
					pantallaPausa = crearPantallaPausa();
					camara.setChaseEntity(null);
					Nivel1.this.attachChild(pantallaPausa);
					camara.setHUD(null);
					btnPausa.setVisible(false);
				}
				return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX,
						pTouchAreaLocalY);
			}
		};
		this.registerTouchArea(btnPausa);
		this.attachChild(btnPausa);
	}
	
	private void guardarScore(int score) {
		if (leerScoreAnterior(LV1_SCORE) <= score) {
			SharedPreferences prefs = gActivity.getSharedPreferences(PROGRESS, 0);
			SharedPreferences.Editor editor = prefs.edit();
			editor.putInt(LV1_SCORE, score);
			editor.commit();
		} else {}
	}
}